/* License Notice:
**
** This program is free software: you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation, either version 3 of the License, or
**    (at your option) any later version.
** This program is distributed in the hope that it will be useful,
**   but WITHOUT ANY WARRANTY; without even the implied warranty of
**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
**   GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
**   along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

/**
 * @file music_sources.hpp
 * @author TooOld2Rock'nRoll
 * @date 2024/09/02
 * @brief Implements Audio Sources for Music Containers.
 */
#ifndef _MUSIC_SOURCES_HPP_
#define _MUSIC_SOURCES_HPP_

/*---- Includes ----*/
#include "audio_interfaces.hpp"


/*---- Typedefs ----*/
/**
 * @brief Function signature for callback to handle music streaming.
 *
 * The underling API will trigger the callback whenever it is ready to receive more data to be mixed in with the
 *   other sounds.<br>
 * It is expecting the data to be in the same format as the opened audio device.<br>
 *
 * @warning <b>Do not</b> change the buffer size, only its content!
 * @remarks Be fast and efficient, using this may block audio processing for the library.
 *
 * @param obj_this - just cast it to Audio::Music.
 * @param[out] buffer - the audio stream buffer ready to be mixed into the audio device.
 * @param[in] len - the length of the buffer array to work with.
 *
 * @todo change to <code>typedef Mix_MixCallback music_streaming_cb</code> when upgrading to SDL3.
 */
typedef void (SDLCALL *music_streaming_cb)(void *obj_this, Uint8 *buffer, int len);


/*---- Class Declaration ----*/
/**
 * @brief Mix_Music data source.
 * A Sound Source that is long and probably compressed, to be decoded on the fly when playback starts.
 */
class UndecodedFileSource : public AudioSourceData<Mix_Music *>
{
    public:
        explicit UndecodedFileSource (const char *file_path);
        virtual ~UndecodedFileSource ();

        /** @brief Sets this specific Music playback volume (from 0 to 100). */
        virtual void setVol (unsigned short volume) override final { this->us_volume = (volume <= 100 ? volume : 100); };
};//END UndecodedFileSource


/**
 * @brief Music Live Streaming data source.
 * A Sound Source that is read from a buffer in memory chunks as they are needed.
 */
class MusicStreamSource : public AudioSourceData<music_streaming_cb>
{
    protected:
        /** @brief This method will be called immediately afer playback starts and every time the native audio queue
         *            finishes processing the previous buffer.
         * @see music_streaming_cb
         * @param[out] buffer - the audio stream buffer ready to be mixed into the audio device.
         * @param[in] len - the length of the buffer array to work with.
         */
        virtual void _fill_stream_cb (Uint8 *buffer, int len) = 0;

    public:
        explicit MusicStreamSource ();
        /** @brief Destructor.  */
        virtual ~MusicStreamSource () {  }

        /** @brief Sets this specific Music playback volume (from 0 to 100).
         * It will still be mixed against the master volume that regulates all sounds.
         */
        virtual void setVol (unsigned short volume) override final { this->us_volume = (volume <= 100 ? volume : 100); };
};//END MusicStreamSource

#endif //_MUSIC_SOURCES_HPP_

